package 数据结构.树;

import java.util.ArrayList;

/**
 * @author Zhu
 * @Description
 * @create 2023-03-04
 */

public class JZ8二叉树的下一个结点 {
    class TreeLinkNode {
        int val;
        TreeLinkNode left = null;
        TreeLinkNode right = null;
        TreeLinkNode next = null;

        TreeLinkNode(int val) {
            this.val = val;
        }
    }
    //给定一个二叉树其中的一个结点，请找出中序遍历顺序的下一个结点并且返回。
    //中序遍历递归
    ArrayList<TreeLinkNode> nodes = new ArrayList<>();
    public TreeLinkNode GetNext(TreeLinkNode pNode) {
        // 获取根节点
        TreeLinkNode root = pNode;
        while(root.next != null) root = root.next;

        // 中序遍历打造nodes
        InOrder(root);

        // 进行匹配
        int n = nodes.size();
        for(int i = 0; i < n - 1; i++) {
            TreeLinkNode cur = nodes.get(i);
            if(pNode == cur) {
                return nodes.get(i+1);
            }
        }
        return null;
    }

    // 中序遍历
    void InOrder(TreeLinkNode root) {
        if(root != null) {
            InOrder(root.left);
            nodes.add(root);
            InOrder(root.right);
        }
    }


    //分类直接寻找
    //直接寻找分为三种情况
        //1.如果给出的结点有右子节点，则最终要返回的下一个结点即右子树的最左下的结点
        //2.如果给出的结点无右子节点，且当前结点是其父节点的左子节点，则返回其父节点
        //3.如果给出的结点无右子节点，且当前结点是其父节点的右子节点，
        //则先要沿着左上方父节点爬树，一直爬到当前结点是其父节点的左子节点为止，返回的就是这个父节点；
        // 或者没有满足上述情况的则返回为NULL
    public TreeLinkNode GetNext2(TreeLinkNode pNode) {
        // 情况一
        if(pNode.right != null) {
            TreeLinkNode rchild = pNode.right;
            // 一直找到右子树的最左下的结点为返回值
            while(rchild.left != null) rchild = rchild.left;
            return rchild;
        }

        // 情况二
        if(pNode.next != null && pNode.next.left == pNode) {
            return pNode.next;
        }

        // 情况三
        if(pNode.next != null) {
            TreeLinkNode ppar = pNode.next;
            // 沿着左上一直爬树，爬到当前结点是其父节点的左自己结点为止
            while(ppar.next != null && ppar.next.right == ppar) ppar = ppar.next;
            return ppar.next;
        }
        return null;
    }
}
